﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;

namespace SampleDataTools
{
    public class UDPWork : IDisposable
    {
        private WorkItem[] workItems;
        private Thread WriteWorkThread;
        private Thread ReceiveWorkThread;
        private bool IsWorkThreadAlive;
        private string LastErrorMessage;

        private DirectoryInfo TempDirInfo;
        public UDPWork()
        {
            TempDirInfo = new DirectoryInfo("Temp");
        }

        public string GetLastErrorMessage()
        {
            string temp = LastErrorMessage;
            if (!string.IsNullOrEmpty(temp))
            {
                LastErrorMessage = null;
            }
            return temp;
        }

        public void Start(ItemConfig[] items)
        {
            if (items == null)
            {
                return;
            }

            if ((WriteWorkThread != null && WriteWorkThread.IsAlive) || (ReceiveWorkThread != null && ReceiveWorkThread.IsAlive))
            {
                ForceStop();
                Stop();
            }

            workItems = items.Select(x => new WorkItem() { Item = x }).ToArray();
            foreach (var worker in workItems)
            {
                worker.Open();
            }

            IsWorkThreadAlive = true;

            WriteWorkThread = new System.Threading.Thread(new System.Threading.ThreadStart(WriteProc))
            {
                Name = "UDP Write file work thread"
            };
            WriteWorkThread.Start();

            ReceiveWorkThread = new System.Threading.Thread(new System.Threading.ThreadStart(ReceiveProc))
            {
                Name = "UDP Receive Work Thread"
            };
            ReceiveWorkThread.Start();
        }

        public void Stop()
        {
            IsWorkThreadAlive = false;

            Clear();
        }

        public void ClearTempDirectory()
        {
            try
            {

                if (TempDirInfo.Exists)
                {
                    TempDirInfo.Delete();
                }

                TempDirInfo.Create();
            }
            catch (Exception)
            { }
        }

        public void CopyToDir(string dir)
        {
            if (TempDirInfo.Exists)
            {
                foreach (var item in TempDirInfo.GetFiles())
                {
                    item.CopyTo(dir + "//" + item.Name, true);
                }
            }
        }

        public BuffData[] GetBuffDatas()
        {
            return workItems?.Select(x => x.LastDataWriteToFile).ToArray();
        }

        private void Clear()
        {
            var tempItems = workItems;

            workItems = new WorkItem[0];

            if (tempItems != null)
            {
                foreach (var item in tempItems)
                {
                    try
                    {
                        item.Close();
                        item.CopyToDirectory(TempDirInfo.FullName);
                    }
                    catch (Exception ex)
                    {
                        LastErrorMessage = ex.Message;
                    }
                }
            }
        }

        private void ForceStop()
        {
            if (WriteWorkThread != null && WriteWorkThread.IsAlive)
            {
                WriteWorkThread.Abort();
            }

            if (ReceiveWorkThread != null && ReceiveWorkThread.IsAlive)
            {
                ReceiveWorkThread.Abort();
            }
            while (WriteWorkThread != null || ReceiveWorkThread != null)
            {
            }
        }

        private void WriteProc(/*object state*/)
        {
            try
            {
                while (IsWorkThreadAlive)
                {
                    // time to rate
                    var flag = workItems.All(x => x.WriteToFile());
                    if (flag)
                    {
                        Thread.Sleep(1);
                    }
                    //foreach (var item in workItems)
                    //{
                    //    item.WriteToFile();
                    //}
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception ex)
            {
                LastErrorMessage = ex.Message;
            }
            finally
            {
                WriteWorkThread = null;
            }
        }

        private void ReceiveProc(/*object state*/)
        {
            try
            {
                while (IsWorkThreadAlive)
                {
                    foreach (var receive in workItems)
                    {
                        try
                        {
                            receive.Receive();
                        }
                        catch (Exception ex)
                        {
                            LastErrorMessage = ex.Message;
                        }
                    }
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                Thread.ResetAbort();
            }
            catch (Exception ex)
            {
                LastErrorMessage = ex.Message;
            }
            finally
            {
                ReceiveWorkThread = null;
            }
        }

        public void Dispose()
        {
            ForceStop();
            Clear();
        }

    }
}
